package {	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.SpreadMethod;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.media.SoundChannel;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import mochi.as3.*;
	
	public class Game extends MovieClip {
		
		private var scorePanel:MovieClip = new ScorePanel();
		private var timePanel:MovieClip = new TimePanel();		
		
		private var bg:MovieClip = new Background();
		private var balanceBar:MovieClip = scorePanel.balance;
		private var _balance:int;
		private var goodPowerBar:MovieClip = new GoodPower();
		private var _goodPower:uint;
		private var evilPowerBar:MovieClip = new EvilPower();
		private var _evilPower:uint;
		
		private var gameLevel:uint;
		private var gameExp:uint;
		private var gameExpTable:Array = [300, 600, 1000, 1100, 1200, 1300, 1500];
		
		private var _score:int;						
		
		private var _persons:Array;
		private var switchs:Array;
		
		private var _combo:uint = 0;
		private var comboTimmer:uint = 0;
		
		private var initTime:Number;
		
		private var soundChannel:SoundChannel = new SoundChannel();
		
		private var _demo:Boolean = true;
		
		
		private var goodPowerButton:MovieClip = new GoodPowerButton();
		private var evilPowerButton:MovieClip = new EvilPowerButton();
		
		public function Game() {												
			addEventListener(Event.ADDED_TO_STAGE, init);		
		}		
		
		private function init(e:Event):void 
		{
			startGame();
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
		}
		
		public function startGame():void 
		{
			//removeChild(e.currentTarget.parent);
			
			drawGame();
		}
		
		private function drawGame():void 
		{
			addChild(bg);						
						
			balanceBar.good.gotoAndStop(1);
			
			goodPowerBar.buttonMode = true;
			evilPowerBar.buttonMode = true;
			
			goodPowerBar.addEventListener(MouseEvent.CLICK, useGoodPower);
			evilPowerBar.addEventListener(MouseEvent.CLICK, useEvilPower);
			goodPowerButton.addEventListener(MouseEvent.CLICK, useGoodPower);
			evilPowerButton.addEventListener(MouseEvent.CLICK, useEvilPower);			
			
			goodPowerButton.buttonMode = true;
			evilPowerButton.buttonMode = true;
			
			goodPowerBar.x = 0;
			evilPowerBar.x = stage.width - evilPowerBar.width + 78;
			
			goodPowerBar.y = 120;
			evilPowerBar.y = 120;								
			
			timePanel.y = 12;
			timePanel.x = 500;
			
			var btnY:int = stage.stageHeight / 2 - goodPowerButton.height / 2 + 30;
			
			goodPowerButton.x = goodPowerBar.x + 35;
			goodPowerButton.y = btnY;
			
			evilPowerButton.x = evilPowerBar.x - 255;
			evilPowerButton.y = btnY;
			
			//addChild(goodPowerButton);
			//addChild(evilPowerButton);
			
			addChild(goodPowerBar);
			addChild(evilPowerBar);								
			
			addChild(scorePanel);
			addChild(timePanel);						
			
			initGame();												
		}
		
		public function initGame():void 
		{							
			balance = 50;
			goodPower = 50;
			evilPower = 50;
			gameLevel = 0;
			gameExp = 0;
			score = 0;
			combo = 1;
			
			var now:Number = new Date().time;
			
			initTime =  now;
			
			persons = new Array();	
			
			switchs = new Array();
			
			createSwitchs();
			
			addEventListener(Event.ENTER_FRAME, enterFrame);	
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);			
		}
		
		public function pause():void 
		{
			removeEventListener(Event.ENTER_FRAME, enterFrame);	
			stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);			
		}
		
		public function unPause():void {
			addEventListener(Event.ENTER_FRAME, enterFrame);	
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);			
		}
		
		private function mouseUp(e:MouseEvent):void 
		{
			for (var i:uint = 0; i < switchs.length; i++ ) {
				var swt:Switch = switchs[i];
				swt.mouseReleased(e);
			}
		}
		
		private function mouseDown(e:MouseEvent):void 
		{
			//if (demo) return;
			var swt:Switch;
			var x:int = e.stageX;
			var y:int = e.stageY;
			
			var xMinOffset = stage.stageWidth / 2 - 5;
			var xOffsetLeft = 200;
			var xOffsetRight = 600;
			
			var yH = 170 * Main.SCALEY;
			
			var pressed:Boolean;
			
			for (var i:uint = 0; i < switchs.length; i++) {
				var swt:Switch = switchs[i];
				if (!(y > 30 + (yH * i) && y < 30 + (yH * (i + 1)))) continue;
				
				if (x < xMinOffset && x > xOffsetLeft) {					
					new GotoHeavenSound().play();
					swt.mouseClickedS1(e);
					pressed = true;					
				}else if (x > xMinOffset && x < xOffsetRight) {
					new GotoHellSound().play();
					swt.mouseClickedS2(e);					
					pressed = true;
				} 								
			}
			
			if (pressed) return;
			
			if (x < xMinOffset) {
				useGoodPower(e);
			}else {
				useEvilPower(e);
			}
			
			/*if (x < xMinOffset && x > xOffsetLeft && y > 30 && y < 200) {
				swt = switchs[0];
				swt.mouseClickedS1(e);
			}else if (x > xMinOffset && x < xOffsetRight && y > 30 && y < 200) {
				swt = switchs[0];
				swt.mouseClickedS2(e);
			}else if (x < xMinOffset && x > xOffsetLeft && y > 200 && y < 370) {
				swt = switchs[1];
				swt.mouseClickedS1(e);
			}else if (x < xMinOffset && x > xOffsetRight && y > 200 && y < 370) {
				swt = switchs[0];
				swt.mouseClickedS1(e);
			}*/
			
			e.stopPropagation();
		}
		
		private function keyup(e:KeyboardEvent):void 
		{
			var down:Boolean = false;
			if (e.keyCode == 39 || e.keyCode == 68) pressRight = down;
			else if (e.keyCode == 37 || e.keyCode == 65) pressLeft = down;
			
			
			else if (e.keyCode == 38 || e.keyCode == 87) {
				swtichIndex--;
				if (swtichIndex < 0) swtichIndex = 2;
			}
			else if (e.keyCode == 40 || e.keyCode == 83) {
				swtichIndex++;
				if (swtichIndex > 2) swtichIndex = 0;
			}
		}
		
		private function keyDown(e:KeyboardEvent):void 
		{
			var down:Boolean = true;
			if (e.keyCode == 39 || e.keyCode == 68) pressRight = down;
			else if (e.keyCode == 37 || e.keyCode == 65) pressLeft = down;
			else if (e.keyCode == 81) useGoodPower(null);
			else if (e.keyCode == 69) useEvilPower(null);
			
		}
		
		private function useGoodPower(e:MouseEvent):void 
		{
			if (goodPowerBar.bar.scaleX == 1) {
				new GoodPowerSound().play();
				goodPower = 0;
				for (var i:uint = 0; i < persons.length; i++ ) {
					var person:Person = persons[i];
					person.type = 2;
				}
			}
		}
		
		
		private function useEvilPower(e:MouseEvent):void 
		{
			if (evilPowerBar.bar.scaleX == 1)	{
				new EvilPowerSound().play();
				evilPower = 0;
				for (var i:uint = 0; i < persons.length; i++ ) {
					var person:Person = persons[i];
					person.type = 3;
				}
			}
		}
		
		private function createSwitchs():void 
		{
			for (var x:uint = 0; x < 3; x++) {
				var swt:Switch = new Switch();
				swt.x = stage.stageWidth / 2 - swt.width / 2;
				swt.y = 115 + 154 * x;
				swt.hitbox.visible = false;
				
				switchs.push(swt);
				addChild(swt);
			}
		}
		
		
		private var totalSpawnDelay:uint = 105;
		private var spawnDelay:uint = 20;	
		private var pressRight:Boolean;
		private var pressLeft:Boolean;
		private var swtichIndex:int;
		private var canPlayReadySnd:Array = [false,false];
		
		private function enterFrame(e:Event):void 
		{
			/*if (demo) {
				alpha = 0.7;
				timePanel.visible = false;
				scorePanel.visible = false;
				goodPowerBar.visible = false;
				evilPowerBar.visible = false;				
				gameExp = 0;
			}
			else {
				alpha = 1;
				timePanel.visible = true;
				scorePanel.visible = true;
				goodPowerBar.visible = true;
				evilPowerBar.visible = true;
			}*/
			
			var passedTime:int = (new Date().time - initTime) / 1000;
			
			timePanel.txt.text = "" + (60 - passedTime);
			balanceBar.good.scaleX = Math.min(Math.max(balance / 100, 0), 1);
			
			if ((60 - passedTime <= 0 || balanceBar.good.scaleX == 0) && !demo) {
				//gameOver();
				//ereturn;
			}
			
			score = Math.max(0, score);
			
			scorePanel.score.text = "" + score;				
			scorePanel.combo.text = ""+  combo;
			
			if (comboTimmer <= 0) combo = 1;
			else comboTimmer--;						
			
			goodPowerBar.bar.scaleX = Math.min(Math.max(goodPower / 100, 0), 1);
			if (goodPowerBar.bar.scaleX < 0.5) goodPowerBar.bar.y = 440;
			else if (goodPowerBar.bar.scaleX < 0.9) goodPowerBar.bar.y = 450;
			else goodPowerBar.bar.y = 455;
			evilPowerBar.bar.scaleX = Math.min(Math.max(evilPower / 100, 0), 1);						
			if (evilPowerBar.bar.scaleX < 0.3) evilPowerBar.bar.y = 435;
			else if (evilPowerBar.bar.scaleX < 0.9) evilPowerBar.bar.y = 445;
			else evilPowerBar.bar.y = 455;
			
			var bars:Array = [goodPowerBar, evilPowerBar];
			
			for (var i:uint; i < bars.length; i++) {
				var mbar:MovieClip = bars[i];
				var bar:MovieClip = mbar.bar;
				//bar.stop();
				
				if (bar.scaleX == 1) {
					bar.play();
					if (canPlayReadySnd[i]) {
						if (i == 0) new GoodPowerReadySound().play();
						else new EvilPowerReadySound().play();
						canPlayReadySnd[i] = false;
						mbar.useBtn.visible = true;
					}
				}else{
					canPlayReadySnd[i] = true;
					bar.gotoAndStop(1);
					mbar.useBtn.visible = false;
				}
			}
			
			if (gameExp % 400 == 0 && gameExp != 0) {
				createPerson(3);
			}
			
			if (gameExp % 900 == 0 && gameExp != 0) {
				createDoublePerson(3);
			}
			
			if (gameExp % 1500 == 0 && gameExp != 0) {
				createTriplePerson(3);
			}
			
			//if (spawnDelay <= 0) {
				spawnDelay = totalSpawnDelay - Math.min(100, (20 * gameLevel)) + ((int) (Math.random() * 30));
				makeSpawn();
			//}else {
				spawnDelay--;
			//}
			
			/*for (var i:uint = 0; i < persons.length; i++ ) {
				var person:Person = persons[i];
				
				if (i < persons.length - 1) {
					var nextPerson:Person = persons[i + 1];	
					if (person.hitTestObject(nextPerson)) {
						person.addColisionRate();
					}
				}
			}*/
			
			for (var i:uint = 0; i < persons.length; i++ ) {
				var person:Person = persons[i];			
				
				var stageQuarter:int = stage.stageWidth / 3 + 36;
				var personType = person.type;
				if (person.x <= stageQuarter + person.width) {
					if (personType == 2) {
						person.rightPassage();
						comboTimmer += 20;
					}
					else {
						person.wrongPassage();
						combo = 1;
						comboTimmer = 0;
					}
					persons.splice(i, 1);
					gameExp += 100;
				}else if (person.x >= stage.stageWidth - stageQuarter - person.width) {
					if (personType == 3) {
						person.rightPassage();
						combo++;
						comboTimmer += 100;
					}
					else {
						person.wrongPassage();
						combo = 1;
						comboTimmer = 0;
					}
					persons.splice(i, 1);
					gameExp += 100;
				}else if (person.y >= stage.stageHeight - (100 * (1- Main.SCALEY))) {
					if (personType == 1) {
						person.rightPassage();
						comboTimmer += 20;
					}
					else {
						person.wrongPassage();
						combo = 1;
						comboTimmer = 0;
					}
					persons.splice(i, 1);
					gameExp += 100;
				}
				
				for (var j:uint = 0; j < switchs.length; j++ ) {
					var swt:Switch = switchs[j];
					if (person.y < switchs.y) break;
					if ( person.hitbox.hitTestObject(swt.hitbox)) {
						var state:uint = swt.getState();
						person.changeState(state);
						if(state != 0) person.converted = true;
					}
				}
			}
			
			/*for (var j:uint = 0; j < switchs.length; j++ ) {
				var swt:Switch = switchs[j];					
				if (pressRight) swt.state = 2;
				else if (pressLeft) swt.state = 1;
				else swt.state = 0;
				if (j == swtichIndex) swt.active = true;
				else swt.active = false;
			}*/
			
			//if (gameLevel > 3 && gameExp % 100 == 0) balance--;
			
			gameExp += 3;
			if (gameExp >= gameExpTable[Math.min(gameExpTable.length, gameLevel)]) {
				gameLevel++;
				gameExp = 0;
				
				var text:ScoreText = new ScoreText(48);
				text.width = 200;
				text.x = stage.stageWidth / 2 - text.width + 130;
				text.y = stage.stageHeight / 2 - text.height;				
				text.text = "Level " + gameLevel;
				text.textColor = 0x990099;
				
				addChild(text);
			}
		}	
		
		private function makeSpawn():void 
		{
			if (((int) (Math.random() * (10  - Math.min(7, gameLevel % 2))) == 0)) {
				createTriplePerson();
			}else if (((int) (Math.random() * (7  - Math.min(5, gameLevel % 2))) == 0)) {
				createDoublePerson();
			}else {
				createPerson();
			}
		}
		
		private function gameOver():void 
		{					
			removeEventListener(Event.ENTER_FRAME, enterFrame);
			
			for (var i:uint = 0; i < persons.length; i++ ) {				
				var person:Person = persons[i];
				
				removeChild(person);
			}
			
			for (var i:uint = 0; i < switchs.length; i++ ) {				
				var swt:Switch = switchs[i];
				
				removeChild(swt);
			}						
			
			/*var o:Object = { n: [14, 15, 13, 13, 0, 13, 2, 12, 5, 1, 0, 13, 0, 1, 15, 12], f: function (i:Number,s:String):String { if (s.length == 16) return s; return this.f(i+1,s + this.n[i].toString(16));}};
			var boardID:String = o.f(0,"");
			MochiScores.showLeaderboard( { boardID: boardID, score: score, onClose: onClose } );												*/
			onClose();
		}
		
		private function onClose():void 
		{
			initGame();
		}
		
		private function createPerson(type:uint = 0, x:int = 0, y:int = -10):void 
		{
			var person:Person = new Person(this, gameLevel, type);
			var offset:int;
			if (x == 0) offset = 40 - ((int) (Math.random() * 80));
			else offset = x;
			person.x = (stage.stageWidth / 2) - (person.width / 2) + offset + 15;
			person.y = y;
			person.hitbox.visible = false;
			persons.push(person);
			addChild(person);			
		}
		
			
		private function createDoublePerson(type:uint = 0):void 
		{
			createPerson(type, -40);
			createPerson(type, 40);
		}
		
		private function createTriplePerson(type:uint = 0):void 
		{
			createDoublePerson(type);			
			createPerson(type, 4);
		}
		
		public function get score():int 
		{
			return _score;
		}
		
		public function set score(value:int):void 
		{
			_score = value;
		}
		
		public function get balance():int 
		{
			return _balance;
		}
		
		public function set balance(value:int):void 
		{
			_balance = value;
		}
		
		public function get goodPower():uint 
		{
			return _goodPower;
		}
		
		public function set goodPower(value:uint):void 
		{
			_goodPower = value;
		}
		
		public function get evilPower():uint 
		{
			return _evilPower;
		}
		
		public function set evilPower(value:uint):void 
		{
			_evilPower = value;
		}
		
		public function get combo():uint 
		{
			return _combo;
		}
		
		public function set combo(value:uint):void 
		{
			_combo = value;
		}
		
		public function get demo():Boolean 
		{
			return _demo;
		}
		
		public function set demo(value:Boolean):void 
		{
			_demo = value;
		}
		
		public function get persons():Array 
		{
			return _persons;
		}
		
		public function set persons(value:Array):void 
		{
			_persons = value;
		}
	}
}
